PC.JSON_RPC = function() {};

// A JSON-RPC implementation on top of the simple json code.
Object.extend(PC.JSON_RPC.prototype, PC.Base.prototype);
Object.extend(PC.JSON_RPC.prototype, {

  initJSON_RPC: function() {
    this.json_request_callbacks = $H({}); // store callbacks by ID
    this.json_current_request_id = 0; // request ID counter
  },

  jsonRequest: function(method, params, callback) {
   var id = this.json_current_request_id++;
   this.json_request_callbacks[id] = callback;

   return({ 'method': method, 
            'params': params || null,
            'id'    : id }.toJSONString());
  },

  jsonResponse: function(result, error, id) {
    return({'result': result || null, 
           'error' : error || null, 
           'id'    : id}.toJSONString());
  },

  jsonNotification: function(method, params) {
    return({ 'method': method, 
            'params': params || null,
            'id'    : null }.toJSONString());
  },

  jsonHandleMsg: function(msg) {
    this.log("Handling raw message:\n" + msg);
    msg = msg.parseJSON();
 
    this.log("Parsed message:\n" + msg);

    // First determine what type of message it is.
    if(msg.method != null && 
       msg.params != null && 
       msg.id != null) { // Request
      return this.handleRequest(msg.method, msg.params, msg.id);

    } else if(msg.id != null) { // Response
      return this.handleResponse(msg.result, msg.error, msg.id);

    } else if(msg.method != null && 
       msg.params != null && 
       msg.id == null) { // Notification
      return this.handleNotification(msg.method, msg.params);
    } else {
      throw "Invalid JSON message cannot be handled!";
    }
  },

  handleRequest: function(method, params, id) {
      // TODO: If security is an issue here we can check the method names
      // against a list of approved names, or something like that...
      if(this[request.method]) {
        var result = this[request.method].apply(this, request.params)
        return this.jsonResponse(result, null, id);
      } else {
        return this.jsonResponse(null, "Method Not Found", id);
      }
  },

  handleResponse: function(result, error, id) {
    var callback = this.json_request_callbacks[id];
    if(callback) {
      delete this.json_request_callbacks[id];
      callback(result, error);
    } else {
      throw "Could not find callback for json request: " + id;
    }
  },

  handleNotification: function(method, params) {
    if(this[request.method]) {
      this[request.method].apply(this, request.params)
    }
  }

});
